namespace feng3d
{

    export interface Attributes
    {
        pos: Attribute;
    }

    export class ShaderToy
    {
        private canvas: HTMLCanvasElement;
        private gl: GL;
        private renderAtomic: RenderAtomic;
        private uniforms: ShaderToyUniforms;
        private shaderCode = "";
        private shader: ShaderToyShader;

        constructor()
        {
            // init WebGL
            this.initGL();

            // init renderdata
            this.initRenderData();

            //
            this.update();
        }

        show(shaderPath: string)
        {
            loader.loadText(shaderPath, (code) =>
            {
                this.setShaderCode(code);
            })
        }

        setShaderCode(shaderCode: string)
        {
            this.shaderCode = shaderCode;
            this.shader.setShaderToyCode(this.shaderCode);
        }

        private initGL()
        {
            // init canvas
            var canvas = <HTMLCanvasElement>document.getElementById("glcanvas");
            if (!canvas)
            {
                canvas = document.createElement("canvas");
                canvas.id = "glcanvas";
                canvas.style.position = "fixed";
                canvas.style.left = "0px";
                canvas.style.top = "0px";
                canvas.style.width = "100%";
                canvas.style.height = "100%";
                document.body.appendChild(canvas);
            }

            this.canvas = canvas;
            this.gl = GL.getGL(canvas);
        }

        private initRenderData()
        {
            var renderAtomic = this.renderAtomic = new RenderAtomic();
            var positions = [
                -1, -1,
                1, -1,
                -1, 1,
                1, -1,
                1, 1,
                -1, 1,
            ];
            var indices = [0, 1, 2, 3, 4, 5];

            renderAtomic.attributes.pos = new Attribute("pos", positions, 2);
            renderAtomic.indexBuffer = new Index(indices);

            //
            this.uniforms = new ShaderToyUniforms();
            renderAtomic.uniforms = <any>this.uniforms;
            renderAtomic.renderParams = { frontFace: FrontFace.CCW };
            this.shader = renderAtomic.shader = new ShaderToyShader();
            this.shader.setShaderToyCode(this.shaderCode);
        }

        private update()
        {
            if (this.shaderCode)
            {
                var canvas = this.canvas;
                var gl = this.gl;
                var renderAtomic = this.renderAtomic;
                var uniforms = this.uniforms;

                //
                canvas.width = canvas.clientWidth;
                canvas.height = canvas.clientHeight;

                // 默认渲染
                gl.colorMask(true, true, true, true);
                gl.clearColor(0, 0, 0, 1);
                gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
                gl.enable(gl.DEPTH_TEST);

                //
                uniforms.iTime += 0.09;
                uniforms.iResolution.x = canvas.width;
                uniforms.iResolution.y = canvas.height;

                // render
                gl.render(renderAtomic);
            }

            requestAnimationFrame(this.update.bind(this));
        }
    }
}